package reflect;

import static org.junit.Assert.*;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.junit.Test;

public class ReflectTest {
	@Test
	public void test1() {
		Person person=new Person();
		String s="aa";
		System.out.println(s.getClass().getName());
		System.out.println(person.getClass().getName());
	}

	/**
	 * 三种获取class对象的方式
	 * Class.forName 是用来装载一个类，然后执行static块，不会创建对象，
	 * 不需要import引入包，（forName方法就是包名+类名，好处是可以写在配置
	 * 文件中，然后用的时候装载，大多数框架都是用这种方式）
	 *
	 * https://blog.csdn.net/qq_37465188/article/details/78907726
	 * https://www.cnblogs.com/bethunebtj/p/4680532.html
     */
	@Test
	public void test2() throws ClassNotFoundException{
		Class demo1=Class.forName("reflect.Person");
		Class demo2=new Person().getClass();
		Class demo3=Person.class;
		System.out.println("aa"+demo1.getName());
		System.out.println("bb"+demo2.getName());
		System.out.println("ccc"+demo3.getName());
	}

	/**
	 * 创建对象，返回object，需要强转
     */
	@Test
	public void test3() throws InstantiationException, IllegalAccessException{
		Class clazz=Person.class;
		Person person=(Person)clazz.newInstance();
		person.setId(1);
		System.out.println(person.getId());
	}

	/**
	 * 创建对象，带泛型，不需要强转
	 */
	@Test
	public void test4() throws InstantiationException, IllegalAccessException{
		Class<Person> clazz=Person.class;
		Person person=clazz.newInstance();
		person.setId(1);
		System.out.println(person.getId());
	}

	/**
	 * getConstructors 是获取public的构造方法
	 * 如果获取所有的（private） demo.getDeclaredConstructors();
	 * field，method 同样，还可以传入class对象获取指定类型参数的
	 * 构造方法
     */
	@Test
	public void test5() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		Class demo=Person.class;
		Constructor [] cons=demo.getConstructors();
		Person person1=(Person)cons[1].newInstance();
		Person person2=(Person)cons[0].newInstance(1,"zhang");
		System.out.println(person1.getClass().getName());
		System.out.println(person2.getName());
	}

	/**
	 * 获取接口
	 * @throws Exception
     */
	@Test
	public void test5s() throws Exception{
		Class demo=Person.class;
		Class [] inter=demo.getInterfaces();
		for(int i=0;i<inter.length;i++){
			System.out.println(inter[i].getName());
		}
	}
	@Test
	public void test6(){
		Class demo=Person.class;
		Class superClass=demo.getSuperclass();
		System.out.println(superClass.getName());
	}
	@Test
	public void test7(){
		Class demo=Person.class;
		Constructor [] cons=demo.getConstructors();
		for(int i=0;i<cons.length;i++){
			Class [] c=cons[i].getParameterTypes();
			System.out.println("cc"+Modifier.toString(cons[i].getModifiers())+"-->"+cons[i].getName());
			for(int j=0;j<c.length;j++){
				System.out.println(c[j].getName());
			}
		}
	}
	@Test
	public void test8(){
		Class personClass=Person.class;
		Method [] methods=personClass.getMethods();
		for(int i=0;i<methods.length;i++){
			System.out.println("sss "+methods[i].getName());
			System.out.println(methods[i].getReturnType());
			Class [] para=methods[i].getParameterTypes();
			for(int j=0;j<para.length;j++){
				System.out.println("dd "+para[j].getName());
			}
			
		}
	}
	@Test
	public void test9() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
		Class personClass=Person.class;
		Method method=personClass.getMethod("go",String.class);
		method.invoke(personClass.newInstance(),"20" );
		System.out.println("----->");
		Method []methods=personClass.getMethods();
		for(int i=0;i<methods.length;i++){
		//	System.out.println(methods[i].getName());
			if(methods[i].getName().equals("setName")){
				method.invoke(personClass.newInstance(), "www");
			}
		}
	}
	@Test
	public void test10() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException{
		Class personClass=Person.class;
		Field field1=personClass.getDeclaredField("name");
		Field field2=personClass.getField("id");
		Person person=(Person)personClass.newInstance();

		field2.setAccessible(true);
		System.out.println(person.getAge());
		field1.setAccessible(true);
		field1.set(person, "zhang");
		System.out.println(person.getName());
	}

	@Test
	public void test11(){
		int [] arr={1,2,3,4};
		Class arrClass=arr.getClass().getComponentType();
		System.out.println("dd "+arrClass.getName());
		System.out.println("dd "+Array.getLength(arr));
		System.out.println("bb "+Array.get(arr,0));
		Array.set(arr, 0, 100);
		System.out.println("dd "+Array.get(arr,0));
	}

	/**
	 * 获取数组的class
	 */
	@Test
	public void test12(){
		int [] arr={1,2,3,4,5};
		Class arrClass=arr.getClass().getComponentType();
		Object newArr=Array.newInstance(arrClass, 20);
		System.arraycopy(arr, 0, newArr, 0, arr.length);
		System.out.println(newArr);
		
	}
	@Test
	public void test13(){
		Person person=new Person();
		System.out.println("dd "+person.getClass().getClassLoader().getClass().getName());
		
	}

	/**
	 * ClassLoader.loadClass()和  class.forName() 区别
	 * https://www.cnblogs.com/suibianle/p/6676215.html
	 */
	@Test
	public void test14(){

	}

	@Test
	public void test(){

	}


}
